package com.oh.core.common.codec;

import com.oh.core.common.constant.ConfigConst;
import com.oh.core.entity.MessageEntity;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

public class OhDecoder extends LengthFieldBasedFrameDecoder {

    /**
     *
     * @param maxFrameLength  帧的最大长度
     * @param lengthFieldOffset length字段偏移的地址
     * @param lengthFieldLength length字段所占的字节长
     * @param lengthAdjustment 修改帧数据长度字段中定义的值，可以为负数 因为有时候我们习惯把头部记入长度,若为负数,则说明要推后多少个字段
     * @param initialBytesToStrip 解析时候跳过多少个长度
     * @param failFast 为true，当frame长度超过maxFrameLength时立即报TooLongFrameException异常，为false，读取完整个帧再报异
     */
    public OhDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
    }

    @Override
    protected MessageEntity decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        if(in == null){
            return null;
        }
        if(in.readableBytes() < ConfigConst.HEAD_LEN){
            throw new Exception("字节数不足");
        }
        // 在这里调用父类的方法,实现指得到想要的部分,我在这里全部都要,也可以只要body部分
        in = (ByteBuf) super.decode(ctx, in);
        // 1-1 指令
        byte command = in.readByte();
        // 2-4 魔数
        int MAGIC = in.readInt();
        // 3-4 报文长度
        int length = in.readInt();
        if(in.readableBytes() != length){
            throw new Exception("标记的长度不符合实际长度");
        }
        // 4 读取body
        byte[] body = new byte[length];
        in.readBytes(body);
        // 防止内存泄漏 LEAK: ByteBuf.release() was not called before it's garbage-collected
        in.release();
        return new MessageEntity(command, MAGIC, body);
    }

}
